    <h1 class="pageHeader">Spica Framework - Manual - Hand-on guide</h1>

    <h2 class="header">Hướng dẫn chi tiết (How-to) - Thực hiện Page Caching</h2>
    <p>Đối với các trang web không cần phải sinh lại thường xuyên do dữ liệu không thay đổi nhiều và liên tục
     trong một giai đoạn nhất định thì việc tạo cache cho toàn trang là một cách thường được nhắc đến để
     tăng tốc độ sinh trang và hiệu năng của toàn bộ site. Để làm được việc này, chúng ta cần sử dụng các sự kiện của
     framework bao gồm: <code>spica_context_start</code>, <code>spica_url_resolver_start</code>, <code>spica_dispatcher_stop</code>. Tổng
     quan chung về sự kiện có thể xem trong bài <a href="docs/guide/page/pname/howto_event">Kiến trúc event-oriented và các event trong Spica</a>.</p>

    <h3>Cách thực hiện</h3>
    <p>Việc thực hiện page caching phải thông qua 2 giai đoạn:</p>
    <ul>
        <li>Lưu toàn bộ trang vào cache</li>
        <li>Phục vụ trang từ cache</li>
    </ul>
    <h4>Lưu toàn bộ trang vào cache</h4>

    <p>Thời điểm page được sinh ra chính là thời điểm mà Controller được tạo ra và phương thức của Controller đó được gọi. Sau thời điểm
        này dữ liệu chứa trong body của SpicaResponse chính là nội dung của trang. Như vậy chúng ta có thể sử dụng sự kiện <code>spica_dispatcher_stop</code>
        để thu hồi nội dung trang và lưu trừ trong cache engine.</p>
<pre class="brush: php">
class PageCacheHandler implements SpicaInvokable
{
    public function __invoke()
    {
        $content = SpicaResponse::getBody();
        $option = new SpicaFileCacheConfiguration('/path/to/cachedir', 5);
        $cache  = SpicaCacheManager::factory($option);
        $cache-&gt;set('page_cache_key', $content, 3)
    }
}

Spica::subscribeEvent('spica_dispatcher_stop', new PageCacheHandler());
</pre>

    <p>Page cache key có thể là một chuỗi ID tính toán dưa trên URL hiện thời</p>
<pre class="brush: php">
$pageKey = crc32(SpicaContext::getFullUrl());
</pre>

    <h4>Phục vụ page từ cache</h4>
    <p>Trong khi việc cache toàn bộ trang cần thực hiện ở giai đoạn cuối cùng khi dữ liệu Controller đã thực hiện xong việc lấy
    dữ liệu sống từ data source và sinh trang đầy đủ thì việc phục vụ page cần được thực hiện trước giai đoạn này. Do vậy, chúng ta sẽ
    khai thác sự kiện <code>spica_context_start</code></p>
<pre class="brush: php">
class PageCacheSendingHandler implements SpicaInvokable
{
    public function __invoke()
    {
        $option = new SpicaFileCacheConfiguration('/path/to/cachedir', 5);
        $cache  = SpicaCacheManager::factory($option);
        $content = $cache-&gt;get('page_cache_key');
        SpicaResponse::setBody($content);
        SpicaContext::setResponseReady(true); // important
    }
}

Spica::subscribeEvent('spica_context_start', new PageCacheSendingHandler());
</pre>

    <?php echo $this->fetchBlock('welcome/SpicaDocsNoteBlock'); ?>